<?php
namespace app\data_magic\logic;

use think\Db;
use think\db\Connection;

/**
 * 后台设置的操作逻辑
 */
class Structure
{
    protected $error;
    public function getError()
    {
        return $this->error;
    }

    protected $_config=null;
    protected $_schema=null;
    protected $_database=null;
    /**
     * 获取数据库连接设置
     * @return array
     */
    public function getConfig()
    {
        if($this->_config===null){
            $this->_config=config("database");
            $this->_config['resultset_type']='array';
        }
        return $this->_config;
    }
    /**
     * 获取information_schema数据库的连接
     * @return Connection
     */
    public function getSchema()
    {
        if($this->_schema===null){
            $config=$this->getConfig();
            $config["database"]="information_schema";
            $this->_schema=Db::connect($config);
        }
        return $this->_schema;
    }
    /**
     * 获取当前数据库的连接
     * @return Connection
     */
    public function getDatabase()
    {
        if($this->_database===null){
            $config=$this->getConfig();
            $this->_database=Db::connect($config);
        }
        return $this->_database;
    }
    /**
     * @return array
     */
    public function getDatabaseTableList()
    {
        $database_name=$this->getConfig()["database"];
        return $this->getSchema()->table("TABLES")->where(["TABLE_SCHEMA"=>$database_name])->select();
    }
    /**
     * @param string $table_name
     * @return array
     */
    public function getDatabaseTableDetail($table_name)
    {
        $database_name=$this->getConfig()["database"];
        return $this->getSchema()->table("TABLES")->where(["TABLE_SCHEMA"=>$database_name,"TABLE_NAME"=>$table_name])->find();
    }
    /**
     * @param string $table_name
     * @return array
     */
    public function transDatabaseTableToStructure($table_name)
    {
        $schema=$this->getSchema();
        $database_name=$this->getConfig()["database"];
        $item=$schema->table("TABLES")->where(["TABLE_SCHEMA"=>$database_name,"TABLE_NAME"=>$table_name])->find();
        $columns=$schema->table("COLUMNS")->where(["TABLE_SCHEMA"=>$database_name,"TABLE_NAME"=>$table_name])->select();
        if($item["TABLE_COMMENT"]){
            $title=$item["TABLE_COMMENT"];
        }
        else{
            $title=$table_name;
        }
        $data=[
            "table"=>[
                "name"=>$table_name,
                "title"=>$title,
                "describe"=>$item["TABLE_COMMENT"],
                "primary_key_field"=>""
            ],
            "fields"=>[]
        ];
        foreach($columns as $column){
            if($column["COLUMN_KEY"]==="PRI"){
                $data["table"]["primary_key_field"]=$column["COLUMN_NAME"];
            }
            if($column["COLUMN_COMMENT"]){
                $title=$column["COLUMN_COMMENT"];
            }
            else{
                $title=$column["COLUMN_NAME"];
            }
            $data["fields"][]=[
                "name"=>$column["COLUMN_NAME"],
                "alias"=>"",
                "title"=>$title,
                "describe"=>$column["COLUMN_COMMENT"],
                "data_type"=>$column["DATA_TYPE"],
                "max_length"=>$column["CHARACTER_MAXIMUM_LENGTH"],
                "is_nullable"=>$column["IS_NULLABLE"]==="YES",
                "type"=>"",
                "type_params"=>"",
            ];
        }
        return $data;
    }
    /**
     * StructureModel
     */
    /**
     * @param array $table 表结构
     * @param array $fields 字段结构
     * @return bool|int
     */
    public function createStructure($table,$fields,$flag=[])
    {
        $db=$this->getDatabase();
        $record=$db->table("dm_table")->where(["name"=>$table["name"]])->find();
        if($record){
            $this->error="结构已经存在";
            return false;
        }
        $create_time=time();
        $table["create_time"]=$create_time;
        $table["update_time"]=$create_time;
        $table["write_time"]=0;
        $table_id=$db->table("dm_table")->insertGetId($table);
        if(!$table_id){
            $this->error="插入表结构失败";
            return false;
        }
        foreach($fields as &$field){
            $field["table_id"]=$table_id;
            $field["create_time"]=$create_time;
            $field["update_time"]=0;
        }
        $result=$db->table("dm_field")->insertAll($fields);
        if(!$result){
            $this->error="插入字段结构失败";
            return false;
        }
        if($flag){
            $fields=$db->table("dm_field")->where(["table_id"=>$table_id])->select();
            $update=[];
            foreach($fields as $field){
                foreach($flag as $key => $value){
                    if($field["name"] === $value){
                        $update[$key]=$field["id"];
                    }
                }
            }
        }
        if($update){
            if(!$db->table("dm_table")->where(["id"=>$table_id])->update($update)){
                $this->error="设置主键失败";
                return false;
            }
        }
        $this->createDefaultScene($table_id,$fields,array_values($update));
        return $table_id;
    }
    /**
     * 修改结构中的表属性
     * @param int $id 表id
     * @param array $data 要修改的数据
     */
    public function updateStructureTable($id,$data)
    {
        $db=$this->getDatabase();
        $table=$db->table("dm_table")->where(["id"=>$id])->find();
        if(!$table){
            $this->error="获取结构失败";
            return false;
        }
        //尝试同步修改相关数据表
        $schema=$this->getSchema();
        $old=$schema->query("SHOW TABLES LIKE '".$table["name"]."'");
        if($old){
            if(isset($data["name"])&&$data["name"]!==$table["name"]){
                $sql="ALTER TABLE `".$table["name"]."` RENAME `".$data["name"]."`;";
            }
        }
        return $db->table("dm_table")->where(["id"=>$id])->strict(false)->field(["title","describe","user_id_field","create_time_field","update_time_field"])->update($data);
    }
    /**
     * 修改结构中的字段属性
     * @param int $id 字段id
     * @param array $data 要修改的数据
     */
    public function updateStructureField($id,$data)
    {
        $db=$this->getDatabase();
        $field=$db->table("dm_field")->where(["id"=>$id])->find();
        if(!$field){
            $this->error="获取结构失败";
            return false;
        }
        return $db->table("dm_field")->where(["id"=>$id])->strict(false)->field(["alias","title","describe","type","type_params"])->update($data);
    }
    /**
     * @return array
     */
    public function getStructureList()
    {
        return $this->getDatabase()->table("dm_table")->select();
    }
    /**
     * @param string $id 表id
     * @return array
     */
    public function getStructureDetail($id)
    {
        $db=$this->getDatabase();
        $table=$db->table("dm_table")->where(["id"=>$id])->find();
        if(!$table){
            $this->error="获取结构失败";
            return false;
        }
        $fields=$db->table("dm_field")->where(["table_id"=>$id])->select();
        if(!$fields){
            $this->error="获取字段失败";
            return false;
        }
        $data=[
            "table"=>$table,
            "fields"=>$fields
        ];
        return $data;
    }
    /**
     * @param string $id 字段id
     */
    public function getStructureFieldDetail($id)
    {
        $db=$this->getDatabase();
        return $db->table("dm_field")->where(["id"=>$id])->find();
    }
    /**
     * SceneModel
     */
    public function createScene($data)
    {
        $data["create_time"]=time();
        $data["update_time"]=0;
        return $this->getDatabase()->table("dm_scene")->strict(false)->insert($data);
    }
    /**
     * 创建默认的场景
     */
    public function createDefaultScene($table_id,$fields,$auto)
    {
        $data=["name"=>"default","title"=>"默认","describe"=>"","table_id"=>$table_id,"params"=>""];
        $readable_list=[];
        $writable_list=[];
        foreach($fields as $field){
            $field_id=$field["id"];
            $readable_list[]=$field_id;
            if(!in_array($field_id,$auto)){
                $writable_list[]=$field_id;
            }
        }
        $data["readable"]=implode(",",$readable_list);
        $data["writable"]=implode(",",$writable_list);
        $this->createScene($data);
    }
    public function removeScene($id)
    {
        return $this->getDatabase()->table("dm_scene")->where(["id"=>$id])->delete();
    }
    public function updateScene($id,$data)
    {
        return $this->getDatabase()->table("dm_scene")->where(["id"=>$id])->strict(false)->update($data);
    }
    public function getSceneList($where=[])
    {
        return $this->getDatabase()->table("dm_scene")->where($where)->select();
    }
    public function getSceneDetail($id)
    {
        return $this->getDatabase()->table("dm_scene")->where(["id"=>$id])->find();
    }
    /**
     * FilterModel
     */
    public function createFilter($data)
    {
        return $this->getDatabase()->table("dm_filter")->strict(false)->insert($data);
    }
    public function removeFilter($id)
    {
        return $this->getDatabase()->table("dm_filter")->where(["id"=>$id])->delete();
    }
    public function updateFilter($id,$data)
    {
        return $this->getDatabase()->table("dm_filter")->where(["id"=>$id])->strict(false)->update($data);
    }
    public function getFilterList($where=[])
    {
        return $this->getDatabase()->table("dm_filter")->where($where)->select();
    }
    public function getFilterDetail($id)
    {
        return $this->getDatabase()->table("dm_filter")->where(["id"=>$id])->find();
    }
    /**
     * ActionModel
     */
    public function createAction($data)
    {
        return $this->getDatabase()->table("dm_action")->strict(false)->insert($data);
    }
    /**
     * 创建默认操作组:用户有权创建和查看
     */
    public function createUserActionGroup($table_id,$scene_id)
    {
        $connet=$this->getDatabase();
        $base_data=[
            "table_id"=>$table_id,
            "scene_id"=>$scene_id,
            "describe"=>"",
            "auth"=>"",
            "params"=>"",
            "bind_action"=>0,
            "link_action"=>"",
            "bind_filter"=>""
        ];
        $list_data=array_merge($base_data,["name"=>"list","title"=>"列表","target_type"=>"show","action_type"=>"search","data_type"=>"where"]);
        $list_id=$connet->table("dm_action")->strict(false)->insertGetId($list_data);

        $create_data=array_merge($base_data,["name"=>"create","title"=>"创建","target_type"=>"form","action_type"=>"create","data_type"=>"nope"]);
        $create_id=$connet->table("dm_action")->strict(false)->insertGetId($create_data);

        $insert_data=array_merge($base_data,["name"=>"insert","title"=>"插入","target_type"=>"post","action_type"=>"create","data_type"=>"nope","bind_action"=>$list_id]);
        $insert_id=$connet->table("dm_action")->strict(false)->insertGetId($insert_data);

        $connet->table("dm_action")->where(["id"=>$list_id])->update(["link_action"=>"$create_id"]);
        $connet->table("dm_action")->where(["id"=>$create_id])->update(["bind_action"=>$insert_id]);
        return true;
    }
    /**
     * 创建默认操作组:创建者有权删除和修改
     */
    public function createOwnerActionGroup($table_id,$scene_id)
    {
        $connet=$this->getDatabase();
        $base_data=[
            "table_id"=>$table_id,
            "scene_id"=>$scene_id,
            "describe"=>"",
            "auth"=>"owner",
            "params"=>"",
            "bind_action"=>0,
            "link_action"=>"",
            "bind_filter"=>""
        ];
        $mine_data=array_merge($base_data,["name"=>"mine","title"=>"我的","target_type"=>"show","action_type"=>"search","data_type"=>"nope"]);
        $mine_id=$connet->table("dm_action")->strict(false)->insertGetId($mine_data);

        $edit_data=array_merge($base_data,["name"=>"edit","title"=>"编辑","target_type"=>"form","action_type"=>"update","data_type"=>"single"]);
        $edit_id=$connet->table("dm_action")->strict(false)->insertGetId($edit_data);
        
        $update_data=array_merge($base_data,["name"=>"update","title"=>"更新","target_type"=>"post","action_type"=>"update","data_type"=>"single","bind_action"=>$mine_id]);
        $update_id=$connet->table("dm_action")->strict(false)->insertGetId($update_data);
        
        $delete_data=array_merge($base_data,["name"=>"delete","title"=>"删除","target_type"=>"exec","action_type"=>"remove","data_type"=>"single","bind_action"=>$mine_id]);
        $delete_id=$connet->table("dm_action")->strict(false)->insertGetId($delete_data);
        
        $connet->table("dm_action")->where(["id"=>$mine_id])->update(["link_action"=>"$edit_id,$delete_id"]);
        $connet->table("dm_action")->where(["id"=>$edit_id])->update(["bind_action"=>$update_id]);
        return true;
    }
    public function removeAction($id)
    {
        return $this->getDatabase()->table("dm_action")->where(["id"=>$id])->delete();
    }
    public function updateAction($id,$data)
    {
        return $this->getDatabase()->table("dm_action")->where(["id"=>$id])->strict(false)->update($data);
    }
    public function getActionList($where=[])
    {
        return $this->getDatabase()->table("dm_action")->where($where)->select();
    }
    public function getActionDetail($id)
    {
        return $this->getDatabase()->table("dm_action")->where(["id"=>$id])->find();
    }
}
